/***************************************************************************************************
 *Copyright(C),2010-2017,Sumscope
 *FileName	:  DictManager.h
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2017/04/05
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/
#pragma

#include <core/sync/lock.h>

#include "DictTable.h"
#include "DictType.h"
#include "HTable/HTable.h"

namespace qb {
namespace ht {

class DictTable;
class DictLoaderListener;
class DictManager {
  typedef std::map<kDictType, DictTable*> DictTableMap;
  typedef DictTableMap::iterator DictTableMapIt;
  struct DictState {
    kDictType type;
    int updateid;
    tName64 md5;
  };

  typedef std::map<kDictType, DictState> DictStateMap;
  typedef std::map<int, DictState> DictHistory;  // updateid->DictState
  typedef std::map<kDictType, DictHistory> DictHistoryMap;
  DictTableMap
      m_tables;  // 各个Table表,可能缺少部分,表示此表被卸载了,需要的时候通过AddDictTable加载
  DictStateMap m_table_states;  // 保留在内存中的各个Table的状态
  DictHistoryMap m_table_history;
  DictLoaderListener* m_loadlistener;  // 加载器,只有第一次加载才会使用
  std::vector<kDictType> m_loadorder;  // 加载顺序
  qb::base::CSLock m_state_lock;
  bool m_clear_table;
  bool m_sequence_log;
  int m_notify_count;
  bool m_initialized;

 public:
  static int UnitTest();
  DictManager();
  ~DictManager();

  void Init();
  // 当收到字典更新包的时候调用,all为true表示登录时首次拉取
  void UpdatePack(UpdatePacket* raw, bool all);

  // 每批次所有字典更新包拉取结束后,将字典数据更新到内存容器中
  int SyncToMemory(bool all);
  DictLoaderListener* GetLoadListener();

  // 更新结束后,卸载字典数据
  void Clear();
  void ClearSeqSet();

  // 获取指定字典表的状态:updateid,md5
  const char* GetDictState(kDictType type, int& updateid);

  bool HasEmptyDict();
  bool GetDictSequence(kDictType type, std::vector<int>& sequences);

  // 查询指定字典在当前批次中是否有更新
  bool IsDataUpdated(kDictType type);

  // 查询所有字典在当前批次中是否有更新
  bool IsAnyDataUpdate();

  // 清楚所有字典的更新数据的footprint
  void ClearUpdateSet();

  // 预估所有字典表的大小,以kb为单位,见DictDesc::GetStockDictDesc
  int PredictProgressSize();

  // 只有在"DictSimulateModifyPack"开启的情况下此函数才会被调用,读取本地文件,模拟更改指定券的名称等信息
  int SimulateModifyBondList();

  // 获取指定字典表的记录个数
  int GetRecordCount(kDictType type);

  // 将数据按照加载顺序导出至指定目录
  void ExportData(const char* fullDirectory);
  void SaveSequences(const std::vector<int>& sequences, kDictType type,
                     const char* tag, int id);

  bool RecreateTable(kDictType type);

  void UpdateDictHistory(kDictType type, int updateid, const char* md5);
  int GetUpdateIdBefore(kDictType type, int updateid, char* md5, int capcity);
  bool HasBadDict();

 public:
  void DumpStatus(int mode = 0);
  void UpdateMacroIndex(bool all);
 protected:
  DictTable* GetDictTable(kDictType id);
  DictTable* GetTablePtr(kDictType id);
  int GetLastUpdateSetSize(kDictType type);

  void AddDictTable(kDictType type);
  kDictType GetPackType(const char* updatePack, int size);

  void UpdateDictState(DictTable* table);
  void RemoveBondSpecialLabel(bool all);
};

}  // namespace ht
}  // namespace qb
